---
title: FAQ
---

import { Link } from "../../src/components/Link";
import { AutoSnippet, When } from "../../src/components/CodeSnippet";

Here are some commonly asked questions from the community:

## What is the different between `ref.refresh` and `ref.invalidate`?

You may have noticed that `ref` has two methods to force a provider to recompute,
and wonder how they differ.

It's simpler than you think: `ref.refresh` is nothing but syntax sugar for
`invalidate` + `read`:

```dart
T refresh<T>(provider) {
  invalidate(provider);
  return read(provider);
}
```

If you do not care about the new value of a provider after recomputing it,
then `invalidate` is the way to go.  
If you do, use `refresh` instead.

:::info
This logic is automatically enforced through lint rules.  
If you tried to use `ref.refresh` without using the returned value,
you would get a warning.
:::

The main difference in behavior is by reading the provider right
after invalidating it, the provider **immediately** recomputes.  
Whereas if we call `invalidate` but don't read it right after,
then the update will trigger _later_.

That "later" update is generally at the start of the next frame.
Yet if invalidating a provider which is currently not listened,
then the provider will not be updated until it is listened again.

## Why is there no shared interface between Ref and WidgetRef?

Riverpod voluntarily dissociates `Ref` and `WidgetRef`.  
This is done on purpose to avoid writing code which conditionally
depends on one or the other.

One issue is that `Ref` and `WidgetRef`, although similar looking,
have suble differences.  
Code relying on both would be unreliable in ways that are difficult to spot.

At the same time, relying on `WidgetRef` is equivalent to relying on `BuildContext`.
It is effectively putting your logic in the UI layer, which is not recommended.

---

Such code should be refactored to **always** use `Ref`.

The solution to this problem is typically to move your logic
into a `Notifier` (see <Link documentID="essentials/side_effects" />).  
And then have your logic be a method of that `Notifier`.

This way, when your widgets want to invoke this logic, they can
write something among the line of:

```dart
ref.read(yourNotifierProvider.notifier).yourMethod();
```

And `yourMethod` would use the `Notifier`'s` `Ref` to interact with other providers.

## Why do we need to extend ConsumerWidget instead of using the raw StatelessWidget?

This is due to an unfortunate limitation in the API of `InheritedWidget`s.

There are a few problems:

- It is not possible to implement an "on change" listener with `InheritedWidget`.
  Meaning that something such as `ref.listen` cannot be used with `BuildContext`.

  `State.didChangeDependencies` is the closest thing to it, but it is not reliable.
  One issue is that the life-cycle can be triggered even if no dependency changed,
  especially if your widget tree uses GlobalKeys (and some Flutter widgets already do so internally).

- Widgets listening to an `InheritedWidget` never stop listening to it.
  This is usually fine for pure metadata, such as "theme" or "media query".

  But for business logic, this is a problem.
  Say you use a provider to represent a paginated API.
  As the page offset changes, you wouldn't want your widget to keep listening
  to the previously visible pages.

- `InheritedWidget` has no way to track when widgets stop listening to them.
  Riverpod sometimes rely on tracking whether a provider is listened to or not.

Those are crutial for both the auto dispose mechanism and the ability to
pass arguments to providers.  
And those features are what makes Riverpod so powerful.

Maybe in a distant future, those issues would be fixed. In that case,
Riverpod would migrate to using `BuildContext` instead of `Ref`.
That would enable using `StatelessWidget` instead of `ConsumerWidget`.  
But that's for another time!

## Why doesn't hooks_riverpod exports flutter_hooks?

This is to respect good versioning practices.

While you cannot use `hooks_riverpod` without `flutter_hooks`,
both packages are versioned independently. A breaking change could happen
in one but not the other.

## Why does Riverpod uses `identical` instead of `==` to filter updates in some cases?

Notifiers use `identical` instead of `==` to filter updates.

This is because it is quite common for Riverpod users to also use a code-generator
such as Freezed/built_value for the sake of a copyWith implementation. But they
also override == to deeply compare objects. But a deep object comparison is quite costly.
"Business logic" models tend to have lots of properties. Worse, they also have collections
(lists/maps/...).

At the same time, when using complex "business" objects, most `state = newState` invocations
always result in a notification (otherwise no point in calling the setter). Generally, the main
case where we call `state = newState` when the current state and new states are equal is
for primitive objects (ints, enums, strings, but not lists/classes/...).
But these objects are "canonicalized by default". So if such objects are equal,
they generally are also "identical".

Riverpod using identical to filter updates is therefore an attempt at having
a good default for both worlds. For complex objects where we don't really care
about filtering objects and where == may be expensive due to code-generators
generating an `==` override by default, using `identical` provides an efficient way of notifying listeners.
At the same time, for simple objects, `identical` correctly does filter redundant notifications.

Last but not least, you can change this behavior by overriding the method
`updateShouldNotify` on Notifiers.
